{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7e7cc6c0",
   "metadata": {},
   "source": [
    "# 第一讲 变量"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0c6a152",
   "metadata": {},
   "source": [
    "## 1. 变量\n",
    "\n",
    "### 1.1 什么是变量\n",
    "\n",
    "在Python中，**变量**（variable）是用来存储数据的容器。每个变量都指向一个**值**（value），即与该变量相关联的信息。\n",
    "\n",
    "### 1.2 基本变量使用\n",
    "\n",
    "#### (1) 创建第一个变量\n",
    "\n",
    "让我们在 `hello_world.py` 文件中使用变量："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c9949624",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello Python world!\n"
     ]
    }
   ],
   "source": [
    "# hello_world.py\n",
    "\n",
    "message = \"Hello Python world!\"\n",
    "\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "112ec213",
   "metadata": {},
   "source": [
    "**代码解析:**\n",
    "1. `message = \"Hello Python world!\"` - 创建了一个名为 `message` 的变量，并将字符串 `\"Hello Python world!\"` 赋值给它\n",
    "2. `print(message)` - 打印变量 `message` 中存储的值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b00f3d4c",
   "metadata": {},
   "source": [
    "#### (2) Python解释器的工作过程\n",
    "\n",
    "当Python解释器执行上述代码时：\n",
    "\n",
    "1. **第一行**：将变量 `message` 与文本 `\"Hello Python world!\"` 关联起来\n",
    "2. **第二行**：将与变量 `message` 关联的值打印到屏幕上"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29247a31",
   "metadata": {},
   "source": [
    "#### (3) 变量值的修改\n",
    "\n",
    "##### 重新赋值\n",
    "\n",
    "变量的值可以随时修改。让我们扩展程序："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a055cd05",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello Python world!\n",
      "Hello Python Crash Course world!\n"
     ]
    }
   ],
   "source": [
    "# hello_world.py\n",
    "message = \"Hello Python world!\"\n",
    "print(message)\n",
    "\n",
    "message = \"Hello Python Crash Course world!\"\n",
    "print(message)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd8a9050",
   "metadata": {},
   "source": [
    "**[重要概念]**\n",
    "\n",
    "- 在程序中，可以**随时修改变量的值**\n",
    "- Python将**始终记录变量的最新值**\n",
    "- 当变量被重新赋值时，原来的值会被新值替换"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce79a42d",
   "metadata": {},
   "source": [
    "### 1.3 变量的特点\n",
    "\n",
    "| 特点         | 说明                             |\n",
    "| ------------ | -------------------------------- |\n",
    "| **动态性**   | 变量的值可以在程序运行过程中改变 |\n",
    "| **引用性**   | 变量指向存储在内存中的值         |\n",
    "| **类型灵活** | 同一个变量可以存储不同类型的数据 |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fb9228b",
   "metadata": {},
   "source": [
    "### 1.4 小结\n",
    "\n",
    "- 变量是存储数据的容器\n",
    "- 使用 `=` 运算符进行赋值\n",
    "- 变量名应该具有描述性，便于理解代码含义\n",
    "- 变量的值可以随时修改，Python会跟踪最新的值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69c3c9d5",
   "metadata": {},
   "source": [
    "## 2. 变量的命名和使用\n",
    "\n",
    "### 2.1 变量命名规则（必须遵守）\n",
    "\n",
    "在Python中使用变量时，必须遵守以下规则，违反这些规则将引发错误：\n",
    "\n",
    "#### (1) 字符组成规则\n",
    "\n",
    "- **只能包含**：字母、数字和下划线（_）\n",
    "- **开头规则**：只能以字母或下划线开头，**不能以数字开头**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f9e5a216",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ✅ 正确示例\n",
    "message_1 = \"Hello\"\n",
    "_private_var = \"Secret\"\n",
    "userName = \"Alice\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a44e8fdc",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid decimal literal (3073279597.py, line 2)",
     "output_type": "error",
     "traceback": [
      "  \u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[31m    \u001b[39m\u001b[31m1_message = \"Hello\"  # 不能以数字开头\u001b[39m\n     ^\n\u001b[31mSyntaxError\u001b[39m\u001b[31m:\u001b[39m invalid decimal literal\n"
     ]
    }
   ],
   "source": [
    "# ❌ 错误示例\n",
    "1_message = \"Hello\"  # 不能以数字开头"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2710252",
   "metadata": {},
   "source": [
    "### 2. 空格处理规则\n",
    "\n",
    "- **不能包含空格**\n",
    "- **使用下划线**来分隔单词"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6fe9ba39",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ✅ 正确示例\n",
    "greeting_message = \"Hello World\"\n",
    "user_name = \"Alice\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ee6400f8",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (1287358746.py, line 2)",
     "output_type": "error",
     "traceback": [
      "  \u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[7]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[31m    \u001b[39m\u001b[31mgreeting message = \"Hello World\"  # 包含空格会报错\u001b[39m\n             ^\n\u001b[31mSyntaxError\u001b[39m\u001b[31m:\u001b[39m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "# ❌ 错误示例\n",
    "greeting message = \"Hello World\"  # 包含空格会报错"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccd416b7",
   "metadata": {},
   "source": [
    "### 3. 关键字冲突规则\n",
    "\n",
    "- **不要使用Python关键字**和内置函数名作为变量名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "58f59c78",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid syntax (3160596888.py, line 3)",
     "output_type": "error",
     "traceback": [
      "  \u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[31m    \u001b[39m\u001b[31mif = 5            # if是关键字\u001b[39m\n       ^\n\u001b[31mSyntaxError\u001b[39m\u001b[31m:\u001b[39m invalid syntax\n"
     ]
    }
   ],
   "source": [
    "# ❌ 避免使用的名称\n",
    "print = \"Hello\"    # print是内置函数\n",
    "if = 5            # if是关键字\n",
    "class = \"Math\"    # class是关键字"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1db1777f",
   "metadata": {},
   "source": [
    "### 4. 变量命名指南（最佳实践）\n",
    "\n",
    "#### (1)描述性原则\n",
    "\n",
    "变量名应该**简短且具有描述性**：\n",
    "\n",
    "| 推荐 ✅         | 不推荐 ❌                 | 说明               |\n",
    "| -------------- | ------------------------ | ------------------ |\n",
    "| `name`         | `n`                      | name更清楚表达含义 |\n",
    "| `student_name` | `s_n`                    | 完整单词更易理解   |\n",
    "| `name_length`  | `length_of_persons_name` | 避免过长的变量名   |\n",
    "\n",
    "#### (2) 大小写使用\n",
    "\n",
    "- **推荐使用小写字母**\n",
    "- 用下划线分隔单词（snake_case风格）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b5a4f2c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# ✅ 推荐风格\n",
    "user_age = 25\n",
    "total_score = 100\n",
    "is_valid = True\n",
    "\n",
    "# 可以使用但不推荐\n",
    "UserAge = 25      # 大写字母在Python中有特殊含义\n",
    "totalScore = 100  # 驼峰命名法在Python中不常用"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5c605df",
   "metadata": {},
   "source": [
    "#### (3) 避免混淆字符\n",
    "\n",
    "慎用容易混淆的字符：\n",
    "\n",
    "| 避免使用     | 原因            | 替代方案                       |\n",
    "| ------------ | --------------- | ------------------------------ |\n",
    "| `l`（小写L） | 容易与数字1混淆 | 使用 `length` 或 `list_data`   |\n",
    "| `O`（大写O） | 容易与数字0混淆 | 使用 `output` 或 `object_data` |\n",
    "\n",
    "\n",
    "#### (4) 特殊说明\n",
    "\n",
    "- Unicode字符支持"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b3cf9630",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Python 3支持Unicode字符（但不推荐）\n",
    "姓名 = \"张三\"        # 技术上可行\n",
    "用户年龄 = 25        # 但不推荐使用\n",
    "\n",
    "# 推荐使用英文\n",
    "name = \"张三\"\n",
    "user_age = 25"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9744917",
   "metadata": {},
   "source": [
    "- 大写字母的特殊含义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8df3248c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 大写字母在Python中通常用于：\n",
    "CONSTANT_VALUE = 100    # 常量\n",
    "ClassName = \"MyClass\"   # 类名"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbfb077d",
   "metadata": {},
   "source": [
    "### 5. 实践建议\n",
    "\n",
    "- 好的变量名示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b84c7a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 描述性强，易于理解\n",
    "user_email = \"user@example.com\"\n",
    "total_price = 99.99\n",
    "is_logged_in = True\n",
    "max_attempts = 3\n",
    "current_user_id = 12345"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9017a518",
   "metadata": {},
   "source": [
    "- 避免的变量名示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a3151cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 避免使用无意义的名称\n",
    "x = \"user@example.com\"    # x没有描述性\n",
    "data = 99.99             # data太泛泛\n",
    "flag = True              # flag不够具体\n",
    "temp = 3                 # temp含义不明"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ed133db",
   "metadata": {},
   "source": [
    "### 6. 小结\n",
    "\n",
    "- **规则必须遵守**：字母数字下划线、不以数字开头、不用关键字\n",
    "- **指南提升质量**：简短描述性、小写加下划线、避免混淆字符\n",
    "- **良好习惯**：随着编程经验增加，变量命名会越来越规范\n",
    "- **目标**：让代码更容易阅读和理解"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6704f8f6",
   "metadata": {},
   "source": [
    "## 3. 如何在使用变量时避免命名错误\n",
    "\n",
    "### 3.1 错误是编程的一部分\n",
    "\n",
    "> **重要提醒**：程序员都会犯错，而且大多数程序员每天都会犯错。虽然优秀的程序员也会犯错，但他们知道如何高效地排除错误。\n",
    "\n",
    "### 3.2 常见的变量命名错误\n",
    "\n",
    "#### (1) 拼写错误示例\n",
    "\n",
    "让我们故意制造一个错误来学习如何调试："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8f04146c",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'mesage' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNameError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 3\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;66;03m# 故意的错误示例\u001b[39;00m\n\u001b[32m      2\u001b[39m message = \u001b[33m\"\u001b[39m\u001b[33mHello Python Crash Course reader!\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m3\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[43mmesage\u001b[49m)  \u001b[38;5;66;03m# 注意：这里少了一个字母 's'\u001b[39;00m\n",
      "\u001b[31mNameError\u001b[39m: name 'mesage' is not defined"
     ]
    }
   ],
   "source": [
    "# 故意的错误示例\n",
    "message = \"Hello Python Crash Course reader!\"\n",
    "print(mesage)  # 注意：这里少了一个字母 's'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "805dcb58",
   "metadata": {},
   "source": [
    "### 3.3 理解Python的错误信息（Traceback）\n",
    "\n",
    "当程序存在错误时，Python解释器会提供一个**traceback**（错误追踪信息）："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "061c087f",
   "metadata": {
    "vscode": {
     "languageId": "bat"
    }
   },
   "outputs": [],
   "source": [
    "Traceback (most recent call last):\n",
    "  File \"hello_world.py\", line 2, in <module>\n",
    "    print(mesage)\n",
    "          ^^^^^^\n",
    "NameError: name 'mesage' is not defined. Did you mean: 'message'?"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a0b8e68",
   "metadata": {},
   "source": [
    "**Traceback信息解读**\n",
    "\n",
    "| 组成部分     | 说明                     | 示例中的信息                    |\n",
    "| ------------ | ------------------------ | ------------------------------- |\n",
    "| **文件位置** | 指出错误发生的文件和行号 | `File \"hello_world.py\", line 2` |\n",
    "| **错误代码** | 显示出问题的具体代码行   | `print(mesage)`                 |\n",
    "| **错误类型** | 说明错误的性质           | `NameError`                     |\n",
    "| **错误描述** | 详细说明问题所在         | `name 'mesage' is not defined`  |\n",
    "| **建议修复** | Python的智能提示         | `Did you mean: 'message'?`      |\n",
    "\n",
    "\n",
    "### 3.4 NameError的常见原因\n",
    "\n",
    "**NameError**通常意味着两种情况：\n",
    "\n",
    "- 使用未定义的变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "870f9b57",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 错误：使用了未定义的变量\n",
    "print(username)  # username从未被定义\n",
    "\n",
    "# 正确：先定义再使用\n",
    "username = \"Alice\"\n",
    "print(username)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc544cd7",
   "metadata": {},
   "source": [
    "- 变量名拼写错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db0664d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 错误：拼写不一致\n",
    "user_name = \"Bob\"\n",
    "print(user_nam)  # 少了一个字母 'e'\n",
    "\n",
    "# 正确：拼写一致\n",
    "user_name = \"Bob\"\n",
    "print(user_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e304904",
   "metadata": {},
   "source": [
    "### 3.5 拼写一致性的重要性\n",
    "\n",
    "- 定义和使用都拼写错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "58aa5d88",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello Python Crash Course reader!\n"
     ]
    }
   ],
   "source": [
    "# 如果定义和使用的拼写都是错误但一致的\n",
    "mesage = \"Hello Python Crash Course reader!\"\n",
    "print(mesage)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4dbeaf3c",
   "metadata": {},
   "source": [
    "#### 重要概念\n",
    "\n",
    "- **变量名一致性**：Python要求变量名拼写完全一致\n",
    "- **语言严格性**：编程语言要求严格，但不关心拼写是否符合英语规范\n",
    "- **无须考虑语法**：在创建变量名时，无须考虑英语中的拼写和语法规则"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63190198",
   "metadata": {},
   "source": [
    "### 3.6 调试技巧和建议\n",
    "\n",
    "#### (1) 仔细检查拼写\n",
    "\n",
    "- 常见的拼写错误\n",
    "    - mesage vs message\n",
    "    - lenght vs length\n",
    "    - hieght vs height\n",
    "\n",
    "#### (2) 使用IDE的帮助\n",
    "\n",
    "- 现代代码编辑器会高亮未定义的变量\n",
    "- 自动补全功能可以减少拼写错误\n",
    "- 语法检查工具可以提前发现问题\n",
    "\n",
    "#### (3) 变量命名最佳实践"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "cf2abff4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用描述性的名称，减少混淆\n",
    "user_email = \"user@example.com\"    # 清晰明确\n",
    "total_price = 99.99                # 含义明显\n",
    "is_valid_user = True               # 布尔值含义清楚"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2ffcf60",
   "metadata": {},
   "source": [
    "### 3.6 调试的心态\n",
    "#### (1) 正确的心态\n",
    "\n",
    "- **错误是正常的**：即使是经验丰富的程序员也会犯简单的拼写错误\n",
    "- **耐心调试**：有时一个字符的错误可能需要花费很长时间才能找到\n",
    "- **学习机会**：每个错误都是学习和改进的机会\n",
    "\n",
    "#### (2)调试步骤\n",
    "\n",
    "1. **阅读错误信息**：仔细查看traceback提供的信息\n",
    "2. **检查行号**：定位到具体的错误行\n",
    "3. **对比拼写**：检查变量名的拼写是否一致\n",
    "4. **验证定义**：确认变量是否已经定义\n",
    "5. **测试修复**：修改后重新运行程序\n",
    "\n",
    "### 3.7 预防错误的方法\n",
    "\n",
    "### 1. 命名规范\n",
    "#### (1) 命名规范"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f8b668af",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用一致的命名风格\n",
    "user_name = \"Alice\"      # snake_case风格\n",
    "user_email = \"alice@example.com\"\n",
    "user_age = 25"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ed85fae",
   "metadata": {},
   "source": [
    "#### (2) 变量声明习惯"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98a9c836",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在使用前先声明所有变量\n",
    "name = \"\"\n",
    "age = 0\n",
    "email = \"\"\n",
    "\n",
    "# 然后再赋值和使用\n",
    "name = \"Bob\"\n",
    "age = 30\n",
    "email = \"bob@example.com\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48a636c4",
   "metadata": {},
   "source": [
    "### 3.8 小结\n",
    "\n",
    "- **错误是学习过程的一部分**，不要因为犯错而沮丧\n",
    "- **Traceback是你的朋友**，它提供了解决问题的重要信息\n",
    "- **拼写一致性**比拼写正确性更重要\n",
    "- **仔细检查变量名**是避免NameError的最好方法\n",
    "- **使用工具辅助**，如IDE的语法检查和自动补全功能\n",
    "\n",
    "记住：很多编程错误都很简单，只是在程序的某一行输错了一个字符。为了找出这种错误而花费很长时间的大有人在，这是编程生涯中的常见经历！"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9de5f23d",
   "metadata": {},
   "source": [
    "## 4. 变量是标签\n",
    "### 4.1 重新理解变量的本质\n",
    "#### (1) 传统理解 vs 准确理解\n",
    "\n",
    "| 传统描述               | 准确描述                   |\n",
    "| ---------------------- | -------------------------- |\n",
    "| 变量是存储值的**盒子** | 变量是可以被赋值的**标签** |\n",
    "| 变量\"包含\"值           | 变量\"指向\"特定的值         |\n",
    "\n",
    "### 4.2 为什么这种理解很重要？\n",
    "#### (1) 初学阶段的影响\n",
    "\n",
    "- **刚接触变量时**：传统的\"盒子\"比喻很有帮助，容易理解\n",
    "- **深入学习后**：准确理解变量的工作原理变得至关重要\n",
    "\n",
    "#### (2) 避免意外行为"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23dc6db8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 这种情况可能会让初学者困惑\n",
    "list1 = [1, 2, 3]\n",
    "list2 = list1        # list2指向与list1相同的对象\n",
    "list2.append(4)      # 修改list2\n",
    "print(list1)         # 输出: [1, 2, 3, 4] - list1也被改变了！"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9773cfcd",
   "metadata": {},
   "source": [
    "### 4.3 变量作为标签的概念\n",
    "#### (1) 可视化理解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "704df9bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 当我们写下这行代码时：\n",
    "message = \"Hello World\"\n",
    "\n",
    "# 实际发生的是：\n",
    "# 1. Python在内存中创建字符串对象 \"Hello World\"\n",
    "# 2. 变量名 message 作为标签，指向这个对象"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "676e357b",
   "metadata": {},
   "source": [
    "#### (2) 标签的特性\n",
    "- 标签可以重新指向"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "518eba2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "message = \"Hello World\"    # message指向字符串对象\n",
    "message = \"Goodbye\"        # message现在指向新的字符串对象\n",
    "message = 42              # message现在指向整数对象"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed7737ad",
   "metadata": {},
   "source": [
    "- 多个标签可以指向同一个对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a8cfa003",
   "metadata": {},
   "outputs": [],
   "source": [
    "name1 = \"Alice\"\n",
    "name2 = name1             # name1和name2都指向同一个字符串对象"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd234ab9",
   "metadata": {},
   "source": [
    "- 标签可以被删除"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "10970f89",
   "metadata": {},
   "outputs": [],
   "source": [
    "message = \"Hello\"\n",
    "del message               # 删除标签，但对象可能仍在内存中"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "13a7a07f",
   "metadata": {},
   "source": [
    "#### (3) 实际应用中的差异\n",
    "- 示例1：数字和字符串（不可变对象）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "29d3b10b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "20\n",
      "10\n"
     ]
    }
   ],
   "source": [
    "a = 10\n",
    "b = a        # b指向与a相同的对象\n",
    "a = 20       # a现在指向新的对象\n",
    "print(a)     # 输出: 20\n",
    "print(b)     # 输出: 10 - b仍指向原来的对象"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0bdf2b25",
   "metadata": {},
   "source": [
    "- 示例2：列表（可变对象）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "327b11ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "list_a = [1, 2, 3]\n",
    "list_b = list_a      # 两个标签指向同一个列表对象\n",
    "list_a.append(4)     # 修改列表对象\n",
    "print(list_a)        # 输出: [1, 2, 3, 4]\n",
    "print(list_b)        # 输出: [1, 2, 3, 4] - 同一个对象被修改"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f261507a",
   "metadata": {},
   "source": [
    "#### (4) 理解标签概念的好处\n",
    "- 预测代码行为"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f07fcc36",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 能够准确预测这段代码的结果\n",
    "original = [1, 2, 3]\n",
    "copy_reference = original\n",
    "copy_reference.append(4)\n",
    "# 知道original也会被改变"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d98e5fa1",
   "metadata": {},
   "source": [
    "- 避免常见错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f513d08",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 错误的做法\n",
    "def add_item(my_list=[]):  # 危险的默认参数\n",
    "    my_list.append(\"item\")\n",
    "    return my_list\n",
    "\n",
    "# 正确的做法\n",
    "def add_item(my_list=None):\n",
    "    if my_list is None:\n",
    "        my_list = []\n",
    "    my_list.append(\"item\")\n",
    "    return my_list"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0c6e47f",
   "metadata": {},
   "source": [
    "- 更好的内存管理理解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6d423ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 理解何时对象会被垃圾回收\n",
    "data = [1, 2, 3, 4, 5]  # 创建列表对象\n",
    "backup = data           # 两个标签指向同一对象\n",
    "data = None             # 删除一个标签\n",
    "# 对象仍然存在，因为backup仍然指向它\n",
    "backup = None           # 现在对象可以被垃圾回收"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8dc4ebf3",
   "metadata": {},
   "source": [
    "#### (5) 实用技巧\n",
    "- 使用id()函数查看对象身份"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4ebbf3e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4494320000\n",
      "4494320000\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "a = [1, 2, 3]\n",
    "b = a\n",
    "print(id(a))  # 查看对象的唯一标识符\n",
    "print(id(b))  # 应该与a相同\n",
    "print(a is b) # True - 指向同一对象"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60faa3ea",
   "metadata": {},
   "source": [
    "- 区分浅拷贝和深拷贝"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "a02a4892",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4494771712\n",
      "4494498752\n",
      "4494959232\n",
      "4494268608\n",
      "4494268608\n",
      "4397263616\n",
      "False\n",
      "False\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "import copy\n",
    "\n",
    "original = [[1, 2], [3, 4]]\n",
    "shallow = copy.copy(original)      # 浅拷贝\n",
    "deep = copy.deepcopy(original)     # 深拷贝\n",
    "\n",
    "print(id(original))    # 原始对象的ID\n",
    "print(id(shallow))     # 浅拷贝对象的ID\n",
    "print(id(deep))        # 深拷贝对象的ID\n",
    "print(id(original[0]))       # 原始对象子对象的ID\n",
    "print(id(shallow[0]))        # 浅拷贝对象子对象的ID\n",
    "print(id(deep[0]))           # 深拷贝对象子对象的ID\n",
    "print(original is shallow)        # False - 不同对象\n",
    "print(shallow is deep)            # False - 不同对象\n",
    "print(original[0] is shallow[0])  # True - 浅拷贝\n",
    "print(original[0] is deep[0])     # False - 深拷贝"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb3e07f5",
   "metadata": {},
   "source": [
    "#### 浅拷贝 (Shallow Copy)\n",
    "- 创建一个新对象，但插入的是原始对象中子对象的引用\n",
    "- 只复制对象的第一层，内部的嵌套对象仍然是引用关系\n",
    "- 修改嵌套对象会影响原对象\n",
    "#### 深拷贝 (Deep Copy)\n",
    "- 创建一个完全独立的新对象，包括所有嵌套的子对象\n",
    "- 递归复制对象的所有层级\n",
    "- 修改任何层级的对象都不会影响原对象\n",
    "\n",
    "\n",
    "#### 对象的层级\n",
    "- 第一层（顶层对象）\n",
    "    - 对象本身的容器结构\n",
    "    - 例如：列表、字典、集合等容器对象\n",
    "- 第二层（直接子对象）\n",
    "    - 容器内直接包含的对象\n",
    "    - 例如：列表中的元素、字典中的值\n",
    "- 第三层及更深（嵌套子对象）\n",
    "    - 子对象内部再包含的对象\n",
    "    - 可以无限嵌套下去"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "b0a908d3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 单层对象 ===\n",
      "对象: [1, 2, 3, 'hello']\n",
      "层级分析:\n",
      "- 第1层: 列表容器本身\n",
      "- 第2层: 基本数据类型 (int, str) - 不可变对象\n",
      "\n",
      "=== 两层对象 ===\n",
      "对象: [[1, 2], [3, 4], 'hello']\n",
      "层级分析:\n",
      "- 第1层: 外层列表容器\n",
      "- 第2层: 内层列表 [1,2], [3,4] 和字符串 'hello'\n",
      "- 第3层: 内层列表中的整数\n",
      "\n",
      "=== 三层对象 ===\n",
      "对象: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]\n",
      "层级分析:\n",
      "- 第1层: 最外层列表\n",
      "- 第2层: 中间层列表 [[1,2],[3,4]] 和 [[5,6],[7,8]]\n",
      "- 第3层: 内层列表 [1,2], [3,4], [5,6], [7,8]\n",
      "- 第4层: 最内层的整数\n"
     ]
    }
   ],
   "source": [
    "# 演示不同层级的对象结构\n",
    "\n",
    "print(\"=== 单层对象 ===\")\n",
    "single_level = [1, 2, 3, 'hello']\n",
    "print(f\"对象: {single_level}\")\n",
    "print(\"层级分析:\")\n",
    "print(\"- 第1层: 列表容器本身\")\n",
    "print(\"- 第2层: 基本数据类型 (int, str) - 不可变对象\")\n",
    "\n",
    "print(\"\\n=== 两层对象 ===\")\n",
    "two_level = [[1, 2], [3, 4], 'hello']\n",
    "print(f\"对象: {two_level}\")\n",
    "print(\"层级分析:\")\n",
    "print(\"- 第1层: 外层列表容器\")\n",
    "print(\"- 第2层: 内层列表 [1,2], [3,4] 和字符串 'hello'\")\n",
    "print(\"- 第3层: 内层列表中的整数\")\n",
    "\n",
    "print(\"\\n=== 三层对象 ===\")\n",
    "three_level = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]\n",
    "print(f\"对象: {three_level}\")\n",
    "print(\"层级分析:\")\n",
    "print(\"- 第1层: 最外层列表\")\n",
    "print(\"- 第2层: 中间层列表 [[1,2],[3,4]] 和 [[5,6],[7,8]]\")\n",
    "print(\"- 第3层: 内层列表 [1,2], [3,4], [5,6], [7,8]\")\n",
    "print(\"- 第4层: 最内层的整数\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "331654cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 示例1: [1, 2, 3] ===\n",
      "层级 1: root -> list\n",
      "  容器有 3 个元素，检查每个元素...\n",
      "  层级 2: root[0] -> int\n",
      "    基本数据类型 '1'，深度为 2\n",
      "  层级 2: root[1] -> int\n",
      "    基本数据类型 '2'，深度为 2\n",
      "  层级 2: root[2] -> int\n",
      "    基本数据类型 '3'，深度为 2\n",
      "  最大子深度: 2\n",
      "最终深度: 2\n",
      "\n",
      "=== 示例2: [[1, 2], [3, 4]] ===\n",
      "层级 1: root -> list\n",
      "  容器有 2 个元素，检查每个元素...\n",
      "  层级 2: root[0] -> list\n",
      "    容器有 2 个元素，检查每个元素...\n",
      "    层级 3: root[0][0] -> int\n",
      "      基本数据类型 '1'，深度为 3\n",
      "    层级 3: root[0][1] -> int\n",
      "      基本数据类型 '2'，深度为 3\n",
      "    最大子深度: 3\n",
      "  层级 2: root[1] -> list\n",
      "    容器有 2 个元素，检查每个元素...\n",
      "    层级 3: root[1][0] -> int\n",
      "      基本数据类型 '3'，深度为 3\n",
      "    层级 3: root[1][1] -> int\n",
      "      基本数据类型 '4'，深度为 3\n",
      "    最大子深度: 3\n",
      "  最大子深度: 3\n",
      "最终深度: 3\n",
      "\n",
      "=== 示例3: {'a': 1, 'b': [2, 3]} ===\n",
      "层级 1: root -> dict\n",
      "  字典有 2 个键值对，检查每个值...\n",
      "  层级 2: root.a -> int\n",
      "    基本数据类型 '1'，深度为 2\n",
      "  层级 2: root.b -> list\n",
      "    容器有 2 个元素，检查每个元素...\n",
      "    层级 3: root.b[0] -> int\n",
      "      基本数据类型 '2'，深度为 3\n",
      "    层级 3: root.b[1] -> int\n",
      "      基本数据类型 '3'，深度为 3\n",
      "    最大子深度: 3\n",
      "  最大子深度: 3\n",
      "最终深度: 3\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 详细解释层级深度的计算逻辑\n",
    "\n",
    "def get_depth_with_explanation(obj, current_depth=0, path=\"root\"):\n",
    "    \"\"\"递归计算深度并提供详细解释\"\"\"\n",
    "    print(f\"{'  ' * current_depth}层级 {current_depth + 1}: {path} -> {type(obj).__name__}\")\n",
    "    \n",
    "    if isinstance(obj, (list, tuple)):\n",
    "        if not obj:  # 空容器\n",
    "            print(f\"{'  ' * current_depth}  空容器，深度为 {current_depth + 1}\")\n",
    "            return current_depth + 1\n",
    "        \n",
    "        print(f\"{'  ' * current_depth}  容器有 {len(obj)} 个元素，检查每个元素...\")\n",
    "        depths = []\n",
    "        for i, item in enumerate(obj):\n",
    "            item_depth = get_depth_with_explanation(item, current_depth + 1, f\"{path}[{i}]\")\n",
    "            depths.append(item_depth)\n",
    "        \n",
    "        max_depth = max(depths)\n",
    "        print(f\"{'  ' * current_depth}  最大子深度: {max_depth}\")\n",
    "        return max_depth\n",
    "        \n",
    "    elif isinstance(obj, dict):\n",
    "        if not obj:  # 空字典\n",
    "            print(f\"{'  ' * current_depth}  空字典，深度为 {current_depth + 1}\")\n",
    "            return current_depth + 1\n",
    "            \n",
    "        print(f\"{'  ' * current_depth}  字典有 {len(obj)} 个键值对，检查每个值...\")\n",
    "        depths = []\n",
    "        for key, value in obj.items():\n",
    "            value_depth = get_depth_with_explanation(value, current_depth + 1, f\"{path}.{key}\")\n",
    "            depths.append(value_depth)\n",
    "        \n",
    "        max_depth = max(depths)\n",
    "        print(f\"{'  ' * current_depth}  最大子深度: {max_depth}\")\n",
    "        return max_depth\n",
    "    else:\n",
    "        # 基本数据类型（叶子节点）\n",
    "        print(f\"{'  ' * current_depth}  基本数据类型 '{obj}'，深度为 {current_depth + 1}\")\n",
    "        return current_depth + 1\n",
    "\n",
    "print(\"=== 示例1: [1, 2, 3] ===\")\n",
    "result1 = get_depth_with_explanation([1, 2, 3])\n",
    "print(f\"最终深度: {result1}\\n\")\n",
    "\n",
    "print(\"=== 示例2: [[1, 2], [3, 4]] ===\")\n",
    "result2 = get_depth_with_explanation([[1, 2], [3, 4]])\n",
    "print(f\"最终深度: {result2}\\n\")\n",
    "\n",
    "print(\"=== 示例3: {'a': 1, 'b': [2, 3]} ===\")\n",
    "result3 = get_depth_with_explanation({'a': 1, 'b': [2, 3]})\n",
    "print(f\"最终深度: {result3}\\n\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "531f70e1",
   "metadata": {},
   "source": [
    "## 4.4 小结\n",
    "\n",
    "- **变量是标签**，不是存储值的盒子\n",
    "- **标签指向对象**，多个标签可以指向同一个对象\n",
    "- **理解这个概念**有助于预测代码行为，避免意外错误\n",
    "- **早期理解**这个概念，对后续学习大有帮助\n",
    "- **通过实践**来加深理解，遇到困难时要有耐心\n",
    "\n",
    "> **重要提醒**：这种差别在刚学习编程时可能意义不大，但越早知道越好。你迟早会遇到变量的行为出乎意料的情形，对变量工作原理的准确认识，将有助于你明白代码是如何运行的。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
